﻿#pragma once
#include "Glowna.h"


//#################################################################################################################
//                   zmienne globalne - ustawienie wartości początkowych
//#################################################################################################################	
float Glowna::g_fSpeedmodifier = 1.0f;
bool Glowna::g_bOrbitOn = true;

 LPDIRECT3DDEVICE9 g_pd3dDevice;	//główny uchwyt urzadzenia - globalny

//#################################################################################################################
//                   konstruktor bezargumentowy
//					 zeruje co sie tylko da
//					 ustawia czcionkę na 14ke
//#################################################################################################################
Glowna::Glowna(void):  kFontSize(14) 
{
	 g_hWnd        = NULL;
	 g_pD3D        = NULL;
	 g_pd3dDevice  = NULL;
	 g_matrixStack = NULL;

	 g_fElpasedTime = 0.0f;
	 g_dCurrentTime = 0;
	 g_dLastTime = 0;
	 gFont=NULL;
     camera= NULL;

	 sun = NULL;
	 Merkury = NULL;
	 Venus = NULL;
	 Ziemia = NULL;
	 Mars = NULL;
	 Jowisz = NULL;
	 Saturn = NULL;
     Uran = NULL;
	 Neptun = NULL;	
	 Haleya = NULL;
}

//#################################################################################################################
//					Destruktor
//					pozeruje, nic nie robi
//#################################################################################################################
Glowna::~Glowna(void)
{
}

//#################################################################################################################
//                   na poczastku bylo WINAPI
//					 funkcja główna
//#################################################################################################################
int WINAPI Glowna::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	WNDCLASSEX winClass; 
    MSG        uMsg;

    memset(&uMsg,0,sizeof(uMsg));
    
    winClass.lpszClassName = "Czikeny";
    winClass.cbSize        = sizeof(WNDCLASSEX);
    winClass.style         = CS_HREDRAW | CS_VREDRAW;
    winClass.lpfnWndProc   = WindowProc;
    winClass.hInstance     = hInstance;
    winClass.hIcon         = LoadIcon(hInstance, (LPCTSTR)IDI_DIRECTX_ICON);
    winClass.hIconSm       = LoadIcon(hInstance, (LPCTSTR)IDI_DIRECTX_ICON);
    winClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
    winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    winClass.lpszMenuName  = NULL;
    winClass.cbClsExtra    = 0;
    winClass.cbWndExtra    = 0;

    if( !RegisterClassEx(&winClass) )
        return E_FAIL;

    g_hWnd = CreateWindowEx( NULL, "Czikeny", 
                             "Uklad Sloneczny",
                             WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                             0, 0, 800, 600, NULL, NULL, hInstance, NULL );

    if( g_hWnd == NULL )
        return E_FAIL;

    ShowWindow( g_hWnd, nCmdShow );
    UpdateWindow( g_hWnd );

    init();

    while( uMsg.message != WM_QUIT )
    {
        if( PeekMessage( &uMsg, NULL, 0, 0, PM_REMOVE ) )
        { 
            TranslateMessage( &uMsg );
            DispatchMessage( &uMsg );
        }
        else
        {
            g_dCurrentTime = timeGetTime();
            g_fElpasedTime = (float)((g_dCurrentTime - g_dLastTime) * 0.001);
            g_dLastTime    = g_dCurrentTime;

            render();
        }
    }

    shutDown();

    UnregisterClass( "Czikeny", winClass.hInstance );

    return uMsg.wParam;
}

//#################################################################################################################
//                   świetna nie wiadomo co robiaca funkcja
//					 jednak wysyła komunikaty i inne takie
//#################################################################################################################	
 LRESULT CALLBACK Glowna::WindowProc( HWND   hWnd, UINT   msg, 
									  WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {   
        case WM_KEYDOWN:
        {
            switch( wParam )
            {
                case VK_ESCAPE: PostQuitMessage(0);  
					break;
                case VK_SPACE: g_bOrbitOn = !g_bOrbitOn; 
					break;
                case VK_F1: 
					if(g_fSpeedmodifier<17)
						if(g_fSpeedmodifier==0)
							g_fSpeedmodifier=1./32;
						else
							g_fSpeedmodifier*=2; 
					
					break;
                case VK_F2: 
					if(g_fSpeedmodifier>(1/33))
						g_fSpeedmodifier/=2; 
					else
						g_fSpeedmodifier=0.;
					break;
            }
        }
        break;
        case WM_CLOSE:
        {
            PostQuitMessage(0); 
        }
        case WM_DESTROY:
        {
            PostQuitMessage(0);
        }
        break;
        default:
        {
            return DefWindowProc( hWnd, msg, wParam, lParam );
        }
        break;
    }
    return 0;
}

//#################################################################################################################
//                   funkcja inicjująca
//					KONKRET!
//#################################################################################################################	
void Glowna::init( void )
{
    g_pD3D = Direct3DCreate9( D3D_SDK_VERSION );

    D3DDISPLAYMODE d3ddm;

    g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm );

    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory( &d3dpp, sizeof(d3dpp) );

    d3dpp.Windowed               = TRUE;
    d3dpp.SwapEffect             = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat       = d3ddm.Format;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    d3dpp.PresentationInterval   = D3DPRESENT_INTERVAL_IMMEDIATE;

    g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd,
                          D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                          &d3dpp, &g_pd3dDevice );

    g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
    g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
    g_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);		//D3DFILL_WIREFRAME  D3DFILL_SOLID
	g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE,D3DSHADE_GOURAUD);

 
	//swiate³ko w tunelu
	float odl = float(4.3),
		  odl2 = float(7.5);

	//ile_swiatel
	Swiatlo zrodlo_swiatel[ile_swiatel] = { Swiatlo(odl,odl,odl),
											Swiatlo(odl,odl,-1*odl),
											Swiatlo(odl,-1*odl,odl),
											Swiatlo(odl,-1*odl,-1*odl),
											Swiatlo(-1*odl,-1*odl,-1*odl),
											Swiatlo(-1*odl,-1*odl,odl),
											Swiatlo(-1*odl,odl,odl),
											Swiatlo(-1*odl,odl,-1*odl),
											Swiatlo(odl2,0,0),
											Swiatlo(-1*odl2,0,0),
											Swiatlo(0,0,-1*odl2),
											Swiatlo(0,0,odl2),
											Swiatlo(0,odl2,0),
											Swiatlo(0,-1*odl2,0)
	};
	
	for(int i=0 ; i<ile_swiatel ; i++)			//w³¹cz œwiat³o
	{
		g_pd3dDevice->SetLight( i+1, &(zrodlo_swiatel[i].zwroc_swiatlo()));
		g_pd3dDevice->LightEnable( i+1, TRUE ); 
	}


		//stworzenie widoku i projekcji
  camera = new cCamera();
  camera->Initialize();

		//inicjalizacja obiektów sferycznych
		
	sun = new     Gwiazda( 0.0f, 0,          "slonce3.x",  "Slonce",  "1,392×10^6 km(109 srednic Ziemi)", "");

	Merkury = new Planeta(  125,  80, "merkury2.x", "Merkury", "4879,4 km(0,383 Ziem)",            "57 909 176 km");
	Venus = new   Planeta(  30,  60, "wenus.x", "Wenus", "12 103,7 km(0,949 srednicy Ziemi)", "108 208 926km");
	Ziemia = new  Planeta(  36,  82, "ziemia.x", "Ziemia", "12 756,2 km", "149 597 890 km");
	Mars = new    Planeta(  22,  74, "mars.x", "Mars", "6 804,9 km(0,533 Ziemi)", "227 936 637 km");
	Jowisz = new  Planeta(  27,  81, "jowisz.x", "Jowisz", "142 984 km(11,209 Ziemi)", "778 412 020 km");
	Saturn = new  Planeta(  32,  69, "saturn.x", "Saturn", "120 536 km(9,449 Ziemi)", "1 426 725 413 km");
	Uran = new    Planeta(  45,  70, "uran.x", "Uran", "51 118 km(4,007 srednice Ziemi)", "2 870 972 220 km");
	Neptun = new  Planeta(  27,  84, "neptun.x", "Neptun", "49 500 km", "4 498 252 900 km");
	
	 
	
	//D3DXCreateTextureFromFile(g_pd3dDevice, "dymek2.bmp", &dymTex);
	// czasteczka1.UstawKordy(3,3,3);
	// czasteczka2.UstawKordy(-3,-3,-3);
	// czasteczka3.UstawKordy(5,0,0);


	Punkt vrtpunktyKontrolne[4] = 
	{//bliskosc,,wysokosc,lewo-prawo
		Punkt(-60,40,-150),
		Punkt(-100,10,-10),
		Punkt(-250,-10,30),
		Punkt(500,-30,300)
	};
	Haleya = new Kometa( "slonce3.x", "Kometa Halleya","16,0 × 8,2 × 8,0 km",vrtpunktyKontrolne);

	// Create a D3DX font object
	D3DXCreateFont( g_pd3dDevice, kFontSize, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 
		DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Arial"), &gFont );

    D3DXCreateMatrixStack( 0, &g_matrixStack );

}

//#################################################################################################################
//                   funkcja sprzątająca
//#################################################################################################################	
void Glowna::shutDown( void )
{
    if( g_pd3dDevice != NULL )
        g_pd3dDevice->Release();

    if( g_pD3D != NULL )
        g_pD3D->Release();
}

//#################################################################################################################
//                   funkcja renderująca obraz
//#################################################################################################################	
void Glowna::render( void )
{
	static float dist = 10000000;					//zmienna przechowujaca najmniejsza aktualna odleglosc planety od kamery ; inicjowana duza wartoscia- moze malo eleganckie ale jako tako dzialo;-)			
	static std::string vrAktualnieOpisywanyObiekt = "";			// zmienna przechowujaca nazwe planety ktora ma powyzsza najmnjesza odleglosc planety od kamery

	D3DXMATRIX mMatrix;
    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
                         D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f), 1.0f, 0 );
	
	g_pd3dDevice->BeginScene();
	   
	camera->Update(g_fElpasedTime);
    camera->SetupMatrix(g_pd3dDevice);

	g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );		
    g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );		

	D3DXVECTOR3 cameraPosition = camera->GetCameraPosition();   //pozycja kamery
	D3DXVECTOR3 cameraPositionAfter;							// po transformacji
	
	D3DXVECTOR3 LookAtVector = camera->GetLookAtVector();		// gdzie patrzymy
	D3DXVECTOR3 LookAtVectorAfter;								// po transformacji
	
	

	mMatrix = sun->przeksztalc(g_bOrbitOn, g_fSpeedmodifier, g_fElpasedTime);
	przeksztalcPromien(&mMatrix, &cameraPosition, &cameraPositionAfter, &LookAtVector, &LookAtVectorAfter);		//przeksztalcamy wektor camery oraz ten wektor ktory mowi na co patrzymy za pomoca macierzy transformacji
	sun->rysuj(gFont, cameraPositionAfter, LookAtVectorAfter, &dist, &vrAktualnieOpisywanyObiekt);


	mMatrix = Merkury->przeksztalc(g_bOrbitOn, g_fSpeedmodifier, g_fElpasedTime);
	przeksztalcPromien(&mMatrix, &cameraPosition, &cameraPositionAfter, &LookAtVector, &LookAtVectorAfter);
	Merkury->rysuj(gFont, cameraPositionAfter, LookAtVectorAfter, &dist, &vrAktualnieOpisywanyObiekt);

	mMatrix = Venus->przeksztalc(g_bOrbitOn, g_fSpeedmodifier, g_fElpasedTime);
	przeksztalcPromien(&mMatrix, &cameraPosition, &cameraPositionAfter, &LookAtVector, &LookAtVectorAfter);
	Venus->rysuj(gFont, cameraPositionAfter, LookAtVectorAfter, &dist, &vrAktualnieOpisywanyObiekt);

	mMatrix = Ziemia->przeksztalc(g_bOrbitOn, g_fSpeedmodifier, g_fElpasedTime);
	przeksztalcPromien(&mMatrix, &cameraPosition, &cameraPositionAfter, &LookAtVector, &LookAtVectorAfter);
	Ziemia->rysuj(gFont, cameraPositionAfter, LookAtVectorAfter, &dist, &vrAktualnieOpisywanyObiekt);

	mMatrix = Mars->przeksztalc(g_bOrbitOn, g_fSpeedmodifier, g_fElpasedTime);
	przeksztalcPromien(&mMatrix, &cameraPosition, &cameraPositionAfter, &LookAtVector, &LookAtVectorAfter);
	Mars->rysuj(gFont, cameraPositionAfter, LookAtVectorAfter, &dist, &vrAktualnieOpisywanyObiekt);

	mMatrix = Jowisz->przeksztalc(g_bOrbitOn, g_fSpeedmodifier, g_fElpasedTime);
	przeksztalcPromien(&mMatrix, &cameraPosition, &cameraPositionAfter, &LookAtVector, &LookAtVectorAfter);
	Jowisz->rysuj(gFont, cameraPositionAfter, LookAtVectorAfter, &dist, &vrAktualnieOpisywanyObiekt);

	mMatrix = Saturn->przeksztalc(g_bOrbitOn, g_fSpeedmodifier, g_fElpasedTime);
	przeksztalcPromien(&mMatrix, &cameraPosition, &cameraPositionAfter, &LookAtVector, &LookAtVectorAfter);
	Saturn->rysuj(gFont, cameraPositionAfter, LookAtVectorAfter, &dist, &vrAktualnieOpisywanyObiekt);

	mMatrix = Uran->przeksztalc(g_bOrbitOn, g_fSpeedmodifier, g_fElpasedTime);
	przeksztalcPromien(&mMatrix, &cameraPosition, &cameraPositionAfter, &LookAtVector, &LookAtVectorAfter);
	Uran->rysuj(gFont, cameraPositionAfter, LookAtVectorAfter, &dist, &vrAktualnieOpisywanyObiekt);

	mMatrix = Neptun->przeksztalc(g_bOrbitOn, g_fSpeedmodifier, g_fElpasedTime);
	przeksztalcPromien(&mMatrix, &cameraPosition, &cameraPositionAfter, &LookAtVector, &LookAtVectorAfter);
	Neptun->rysuj(gFont, cameraPositionAfter, LookAtVectorAfter, &dist, &vrAktualnieOpisywanyObiekt);

//#############################################################################################################
//#############################################################################################################
//#############################################################################################################
//#############################################################################################################


	sun->RysujDym();


//#############################################################################################################
//#############################################################################################################
//#############################################################################################################
//#############################################################################################################

	static double t=0.;
	mMatrix = Haleya->przesun(t);
	t+=0.001*g_fSpeedmodifier;        
	if(t>=1)
		t=0;
	przeksztalcPromien(&mMatrix, &cameraPosition, &cameraPositionAfter, &LookAtVector, &LookAtVectorAfter);
	Haleya->rysuj(gFont, cameraPositionAfter, LookAtVectorAfter, &dist, &vrAktualnieOpisywanyObiekt);
	
	Haleya->RysujOgon();
	
	
	
	
	
	//wstawienie celownika na środek ekranu
	D3DCOLOR vrtKolorCzcionki = D3DCOLOR_XRGB(255,255,255);    
	RECT vrtProstokatDlaCelownika;
	vrtProstokatDlaCelownika.left=388;
	vrtProstokatDlaCelownika.top=277;
	
	vrtProstokatDlaCelownika.right=800;
	vrtProstokatDlaCelownika.bottom=640;
		
	gFont->DrawText(NULL, "X", -1, &vrtProstokatDlaCelownika, 0, vrtKolorCzcionki );

    g_pd3dDevice->EndScene();
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );


}

//#################################################################################################################
//                   funkcja przekształcająca promień
//#################################################################################################################	
void Glowna::przeksztalcPromien(D3DXMATRIX* mMatrix, D3DXVECTOR3* eyeIn,  D3DXVECTOR3* eyeOut,  D3DXVECTOR3* lookAtIn,  D3DXVECTOR3* lookAtOut)
{
	D3DXMATRIX* mOdwrotna = new D3DXMATRIX();
	D3DXMatrixInverse(mOdwrotna, NULL, mMatrix);
	
	D3DXVec3TransformCoord(eyeOut, eyeIn, mOdwrotna);
    D3DXVec3TransformNormal(lookAtOut, lookAtIn, mOdwrotna);
}